<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui"
	template="../templates/ui.xhtml">

    <ui:define name="head">
        <style type="text/css">
            
        </style>

        <script type="text/javascript">
            //<![CDATA[
/**
 * JSF Validator
 */
PrimeFaces.validator['custom.emailValidator'] = {
    
    pattern: /\S+@\S+/,
    
    validate: function(element, value) {
        //use element.data() to access validation metadata, in this case there is none.
        if(!this.pattern.test(value)) {
            throw {
                summary: 'Validation Error',
                detail: value + ' is not a valid email.'
            }
        }
    }
};

/**
 * Bean validator for @Email
 */
PrimeFaces.validator['Email'] = {
    
    pattern: /\S+@\S+/,
            
    MESSAGE_ID: 'org.primefaces.examples.validate.email.message',
    
    validate: function(element, value) {
        var vc = PrimeFaces.util.ValidationContext;

        if(!this.pattern.test(value)) {
            var msgStr = element.data('p-email-msg'),
            msg = msgStr ? {summary:msgStr, detail: msgStr} : vc.getMessage(this.MESSAGE_ID);
    
            throw msg;
        }
    }
};
            //]]>
        </script>
    </ui:define>

	<ui:define name="content">
	
		<h1 class="title ui-widget-header ui-corner-all">Client Side Validation - Custom</h1>
		<div class="entry">
			<p>A custom converter or a validator can be implemented easily. Both JSF and Bean Validation APIs are supported.</p>

			<h:form>
                <p:growl showDetail="true"/>
                
                <p:panel header="Validate">
                    <h:panelGrid columns="4" cellpadding="5">
                        <h:outputLabel for="email1" value="Email 1: (JSF Validation)" />
                        <p:inputText id="email1" value="#{validationBean.text}">
                            <f:validator validatorId="custom.emailValidator" />
                        </p:inputText>
                        <p:message for="email1" display="tooltip" />
                        <h:outputText value="#{validationBean.text}" />
                        
                        <h:outputLabel for="email2" value="Email 2: (Bean Validation)" />
                        <p:inputText id="email2" value="#{validationBean.email}" />
                        <p:message for="email2" display="tooltip" />
                        <h:outputText value="#{validationBean.email}" />
                    </h:panelGrid>

                    <p:commandButton value="Save" ajax="false" icon="ui-icon-check" validateClient="true"/>
                </p:panel>
			</h:form>
			
			<h3>Source</h3>
			<p:tabView>
				<p:tab title="csvCustom.xhtml">
                    <pre name="code" class="xml">
&lt;h:form&gt;
    &lt;p:growl showDetail="true"/&gt;

    &lt;p:panel header="Validate"&gt;
        &lt;h:panelGrid columns="3" cellpadding="5"&gt;
            &lt;h:outputLabel for="email1" value="Email 1: (JSF Validation)" /&gt;
            &lt;p:inputText id="email1" value="\#{validationBean.text}"&gt;
                &lt;f:validator validatorId="custom.emailValidator" /&gt;
            &lt;/p:inputText&gt;
            &lt;p:message for="email1" display="tooltip" /&gt;
            &lt;h:outputText value="\#{validationBean.text}" /&gt;

            &lt;h:outputLabel for="email2" value="Email 2: (Bean Validation)" /&gt;
            &lt;p:inputText id="email2" value="\#{validationBean.email}" /&gt;
            &lt;p:message for="email2" display="tooltip" /&gt;
            &lt;h:outputText value="\#{validationBean.email}" /&gt;
        &lt;/h:panelGrid&gt;

        &lt;p:commandButton value="Save" ajax="false" icon="ui-icon-check" validateClient="true"/&gt;
    &lt;/p:panel&gt;
&lt;/h:form&gt;

&lt;script type="text/javascript"&gt;
/**
 * JSF Validator
 */
PrimeFaces.validator['custom.emailValidator'] = {
    
    pattern: /\S+@\S+/,
    
    validate: function(element, value) {
        //use element.data() to access validation metadata, in this case there is none.
        if(!this.pattern.test(value)) {
            throw {
                summary: 'Validation Error',
                detail: value + ' is not a valid email.'
            }
        }
    }
};

/**
 * Bean validator for @Email
 */
PrimeFaces.validator['Email'] = {
    
    pattern: /\S+@\S+/,
            
    MESSAGE_ID: 'org.primefaces.examples.validate.email.message',
    
    validate: function(element, value) {
        var vc = PrimeFaces.util.ValidationContext;

        if(!this.pattern.test(value)) {
            var msgStr = element.data('p-email-msg'),
            msg = msgStr ? {summary:msgStr, detail: msgStr} : vc.getMessage(this.MESSAGE_ID);
    
            throw msg;
        }
    }
};
&lt;/script&gt;
                    </pre>
				</p:tab>
				
				<p:tab title="ValidationBean.java">
<pre name="code" class="java">
package org.primefaces.examples.view;

import org.primefaces.examples.validate.Email;

public class ValidationBean {
    
    private String text;

    @Email(message = "must be a valid email")
    private String email;
    
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }

    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}
</pre>
				</p:tab>
                
                <p:tab title="EmailValidator.java">
<pre name="code" class="java">
package org.primefaces.examples.validate;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import org.primefaces.validate.ClientValidator;

/**
 * Custom JSF Validator for Email input
 */
@FacesValidator("custom.emailValidator")
public class EmailValidator implements Validator, ClientValidator {

    private Pattern pattern;
	private Matcher matcher;
 
	private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
                                                + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
 
	public EmailValidator() {
		pattern = Pattern.compile(EMAIL_PATTERN);
	}

    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if(value == null) {
            return;
        }
        
        if(!pattern.matcher(value.toString()).matches()) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Validation Error", 
                        value + " is not a valid email;"));
        }
    }
    
    public Map&lt;String, Object&gt; getMetadata() {
        return null;
    }

    public String getValidatorId() {
        return "custom.emailValidator";
    }
    
}
</pre>
        </p:tab>
                    
        <p:tab title="Email.java">
<pre name="code" class="java">
package org.primefaces.examples.validate;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import org.primefaces.validate.bean.ClientConstraint;

@Target({METHOD,FIELD,ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy=EmailConstraintValidator.class)
@ClientConstraint(resolvedBy=EmailClientValidationConstraint.class)
@Documented
public @interface Email {
    
    String message() default "{org.primefaces.examples.primefaces}";
    
    Class&lt;?&gt;[] groups() default {};

    Class&lt;? extends Payload&gt;[] payload() default {};
}
</pre>
				</p:tab>
                    
                <p:tab title="EmailConstraintValidator.java">
<pre name="code" class="java">
package org.primefaces.examples.validate;

import java.util.regex.Pattern;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * ConstraintValidator for Email Input
 */
public class EmailConstraintValidator implements ConstraintValidator&lt;Email, String&gt;{

    private Pattern pattern;
 
	private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
                                                + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
    
    public void initialize(Email a) {
        pattern = Pattern.compile(EMAIL_PATTERN);
    }

    public boolean isValid(String value, ConstraintValidatorContext cvc) {
        if(value == null)
            return true;
        else
            return pattern.matcher(value.toString()).matches();
    }
    
}
</pre>
				</p:tab>
                    
                <p:tab title="EmailClientValidationConstraint.java">
<pre name="code" class="java">
package org.primefaces.examples.validate;

import java.util.HashMap;
import java.util.Map;
import javax.validation.metadata.ConstraintDescriptor;
import org.primefaces.validate.bean.ClientValidationConstraint;

/**
 * ClientValidationConstraint for @Email annotation
 */
public class EmailClientValidationConstraint implements ClientValidationConstraint {

    public static final String MESSAGE_METADATA = "data-p-email-msg";
    
    public Map&lt;String, Object&gt; getMetadata(ConstraintDescriptor constraintDescriptor) {
        Map&lt;String,Object&gt; metadata = new HashMap&lt;String, Object&gt;();
        Map attrs = constraintDescriptor.getAttributes();
        Object message = attrs.get("message");    
        if(message != null) {
            metadata.put(MESSAGE_METADATA, message);
        }
        
        return metadata;
    }

    public String getValidatorId() {
        return Email.class.getSimpleName();
    }
    
}
</pre>
				</p:tab>
			</p:tabView>
			
		</div>
				
	</ui:define>
</ui:composition>